import React, { useState, useCallback, useEffect, useMemo } from 'react';
import { Common } from 'UtilsCommon';
import { Input } from 'antd-mobile';
import Components from 'Components';
import Base from './base';
import * as styles from '../styles/view.scss';

const change = (value, property, setValue) => {
    setValue(value);
    Base.bindDataValue(property, value);
};

const valueChange = (property, value) => {
    if (property.valueChange) property.valueChange(value);
};

const renderLabel = (label2, isAddColon, isRed2) => {
    return <div className={styles.divLabel}>
        {isRed2 ? <span className='spRed' style={{ color: 'red' }}>*</span> : ''}
        <span>{label2}{isAddColon ? '：' : ''}</span>
    </div>;
};
const renderEmptyTip = (isEmptyTip, value2) => {
    return <div className={styles.divEmptyTip}>
        {isEmptyTip && Common.isNullOrEmpty(value2) && <span>请输入内容</span>}
    </div>;
};

const renderInput = (property, onChange, onEnterPress, onFocus, onBlur, isReadOnly, disabled, type, clear2, value2) => {
    return (<Input placeholder={property.placeHolder}
        onChange={onChange}
        maxLength={property.maxLength}
        readOnly={isReadOnly}
        disabled={disabled && !isReadOnly}
        type={type}
        clearable={clear2}
        onBlur={onBlur}
        onFocus={onFocus}
        onEnterPress={onEnterPress}
        value={value2}></Input>
    );
};

const renderOption = (m, property, pageAxis, setValue, obj, PropertyItem) => {
    const p = Common.clone(property.properties[0]);
    p.id = Common.createGuid();
    p.data = m;
    const v = m[property.textName];
    p.value = v;
    if (p.properties) {
        p.properties.forEach(p2 => {
            p2.id = Common.createGuid();
            p2.data = m;
            p2.value = v;
        });
    }
    p.eventActionName = 'clickSelectOption';

    pageAxis.clickSelectOption = (props) => {
        const p3 = props.property;
        obj.options = [];
        obj.selectData = p3.data;
        setValue(p3.value);
    };

    return <PropertyItem key={p.id} property={p} view={property} pageId={pageAxis.id} />;
};

const renderOptions = (property, pageAxis, setValue, obj, PropertyItem) => {
    const { optionsStyle } = property;

    return <div style={Base.setStyle(optionsStyle)}>
        {obj.options.map((m) => renderOption(m, property, pageAxis, setValue, obj, PropertyItem))}
    </div>;
};

const getOptions = (property, v, obj, setRefresh) => {
    if (Common.isNullOrEmpty(v)) return;
    if (property.queryData) {
        obj.currentValue = v;

        if (obj.isLoading) {
            obj.hasWaiting = true;
            return;
        }

        if (obj.timeoutId > 0) return;

        const queryData = () => {
            obj.isLoading = true;
            obj.queryValue = obj.currentValue;
            property.queryData(property, obj.currentValue).then(res => {
                obj.options = res;
                obj.isLoading = false;
                setRefresh(Common.createGuid());
                obj.timeoutId = 0;

                if (obj.hasWaiting && obj.queryValue !== obj.currentValue) {
                    obj.hasWaiting = false;
                    obj.timeoutId = setTimeout(() => queryData(), 500);
                }
            });
        };

        obj.timeoutId = setTimeout(() => queryData(), 500);
    }
    else {
        if (!property.maxItemCount) property.maxItemCount = 100;
        let list = property.dataSource || [];
        if (property.selectDataSource) list = property.selectDataSource;

        const options = [];
        v = v.toLowerCase();
        list.forEach(d => {
            const text = (d[property.textName] || '').toLowerCase();
            if (text.indexOf(v) >= 0 && property.maxItemCount > options.length) {
                options.push(d);
            }
        });
        obj.options = options;
    }
};

const getSelectData = (obj, property, value) => {
    if (obj.selectData && Common.isEquals(obj.selectData[property.textName], value)) return obj.selectData;

    return Common.arrayFirst(obj.options, f => Common.isEquals(f[property.textName], value));
};

export default (props) => {
    const { PropertyItem } = Components;
    const { property, view, pageAxis } = Base.getProps(props);
    const [value, setValue] = useState(Base.getInitValue(property));
    const [isVisible, setIsVisible] = useState(property.isVisible !== false);
    const [disabled, setDisabled] = useState(!!property.disabled);
    const [isReadOnly, setIsReadOnly] = useState(!!property.isReadOnly);
    const [isEmptyTip, setIsEmptyTip] = useState(false);
    const [, setRefresh] = useState('');
    const obj = useMemo(() => ({ options: [], selectData: null }), []);

    const onChange = useCallback((v) => {
        property.isChanged = true;
        obj.selectData = null;
        getOptions(property, v, obj, setRefresh);
        change(v, property, setValue);
    }, [property, setValue, obj, setRefresh]);

    const onBlur = useCallback(() => {
        property.onBlur && property.onBlur(value, property);
    }, [property, value]);

    const onFocus = useCallback(() => {
        property.onFocus && property.onFocus(value, property);
    }, [property, value]);

    const onEnterPress = useCallback(() => {
        if (property.enterEventActionName) pageAxis.invokeEventAction(property.enterEventActionName, { property, view, pageAxis });
        else if (property.enterEventAction) pageAxis.invokeEventAction2(property.eventAction, { property, view, pageAxis });
    }, [property, view, pageAxis]);

    useEffect(() => {
        valueChange(property, value);
    }, [property, value]);

    property.setIsVisible = (v) => { property.isVisible = v; setIsVisible(v); };
    property.setValue = (v) => setValue(v);
    property.getValue = () => Base.getValue(property, value);
    property.setDisabled = (v) => setDisabled(v);
    property.setIsReadOnly = (v) => setIsReadOnly(v);
    property.setIsEmptyTip = (v) => setIsEmptyTip(v);
    property.setRefresh = () => setRefresh(Common.createGuid());
    property.getSelectData = () => getSelectData(obj, property, value);
    property.getSelectOptions = () => obj.options;

    if (!isVisible) return null;

    const { label, clear, isRed, isValueVisible, cssTemplate, isAddColon, style } = property;
    let isNullable = property.isNullable;

    if (isValueVisible && !value) return null;

    const type = isReadOnly ? 'text' : (property.controlType || 'text');

    const className = Base.getClassName(property, styles);

    const cNames = [];
    if (className) cNames.push(className);
    if (cssTemplate) cNames.push(cssTemplate.cssName);

    let clear2 = clear === undefined ? true : clear;
    if (isReadOnly || disabled) clear2 = false;

    property.placeHolder = property.placeHolder || (isNullable ? '选填' : '请输入');

    let isRed2 = property.isRed2 || (isNullable === false && isRed);
    if (isReadOnly) {
        isRed2 = false;
        isNullable = true;
        property.placeHolder = '';
    }

    const label2 = property.isLabel === false ? '' : label;

    const value2 = Common.isNullOrEmpty(value) ? '' : value;

    return <div className={cNames.join(' ')} style={Base.setStyle(style)}>
        {label2 && renderLabel(label2, isAddColon, isRed2)}
        {renderInput(property, onChange, onEnterPress, onFocus, onBlur, isReadOnly, disabled, type, clear2, value2)}
        {property.isEmptyTip && renderEmptyTip(isEmptyTip, value2)}
        {value && obj.options.length > 0 && renderOptions(property, pageAxis, setValue, obj, PropertyItem)}
    </div>;
};